package com.tianji.promotion.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.promotion.domain.po.Coupon;
import com.tianji.promotion.domain.po.ExchangeCode;
import com.tianji.promotion.domain.query.CodeQuery;
import com.tianji.promotion.domain.vo.ExchangeCodeVO;
import com.tianji.promotion.enums.ExchangeCodeStatus;
import com.tianji.promotion.mapper.ExchangeCodeMapper;
import com.tianji.promotion.service.IExchangeCodeService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.promotion.utils.CodeUtil;
import jdk.dynalink.linker.LinkerServices;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static com.tianji.promotion.constants.PromotionConstants.*;

/**
 * <p>
 * 兑换码 服务实现类
 * </p>
 *
 * @author taohongrun
 * @since 2025-02-13
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class ExchangeCodeServiceImpl extends ServiceImpl<ExchangeCodeMapper, ExchangeCode> implements IExchangeCodeService {
    private final StringRedisTemplate redisTemplate;
    @Override
    @Async("generateExchangeCodeExecutor")
    public void asyncGenerateCode(Coupon coupon) {
        Integer totalNum = coupon.getTotalNum();
        Long incrementedValue = redisTemplate.opsForValue().increment(COUPON_CODE_SERIAL_KEY, totalNum);
        if (incrementedValue == null) throw new BadRequestException("redis不存在该数据");
        List<ExchangeCode> exchangeCodeList = new ArrayList<>(totalNum);
        for(int i = incrementedValue.intValue() - totalNum + 1; i <= incrementedValue; i++){
            String exchangeCode = CodeUtil.generateCode(i, coupon.getId());
            ExchangeCode ec = new ExchangeCode();
            ec.setCode(exchangeCode);
            ec.setId(i);
            ec.setStatus(ExchangeCodeStatus.UNUSED);
            ec.setType(coupon.getType());
            ec.setExpiredTime(coupon.getIssueEndTime());
            ec.setExchangeTargetId(coupon.getId());
            exchangeCodeList.add(ec);
        }
        saveBatch(exchangeCodeList);
        // 4.写入Redis缓存，member：couponId，score：兑换码的最大序列号
        redisTemplate.opsForZSet().add(COUPON_RANGE_KEY, coupon.getId().toString(), totalNum);
    }

    @Override
    public PageDTO<ExchangeCodeVO> queryCodePage(CodeQuery query) {
        Page<ExchangeCode> page = lambdaQuery()
                .eq(ExchangeCode::getStatus, query.getStatus())
                .eq(ExchangeCode::getExchangeTargetId, query.getCouponId())
                .page(query.toMpPage());
        List<ExchangeCode> records = page.getRecords();
        List<ExchangeCodeVO> l = records.stream().map(m -> {
            return new ExchangeCodeVO(m.getId(), m.getCode());
        }).collect(Collectors.toList());
        return PageDTO.of(page,l);
    }

    @Override
    public boolean updateExchangeMark(long serialNum, boolean b) {
        Boolean b1 = redisTemplate.opsForValue().setBit(COUPON_CODE_MAP_KEY, serialNum, b);
        return b1;
    }
}
